home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 399_01 / minedio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  27.7 KB  |  1,329 lines

  1. /*  ==================================================================    *
  2.  *                Editor mined                *
  3.  *            Operating system dependant I/O            *
  4.  *  ==================================================================    */
  5.  
  6. #include "mined.h"
  7. #include <errno.h>
  8. #include <signal.h>
  9.  
  10. #ifdef CURSES
  11. #include <curses.h>
  12. #undef FALSE
  13. #undef TRUE
  14. #undef TERMIO    /* \ must be  */
  15. #undef SGTTY    /* / disabled */
  16. #endif
  17.  
  18. #ifdef TERMIO
  19. #include <termios.h>
  20. #endif
  21. #ifdef SGTTY
  22. #include <sys/ioctl.h>    /* <sgtty.h> ? */
  23. extern void ioctl ();
  24. #endif
  25.  
  26. #ifdef SIGPHONE        /* this trick was taken from less' screen.c */
  27. #include <sys/window.h>    /* for window size detection */
  28. #endif
  29.  
  30. #ifdef msdos
  31. #define _getch_
  32. #include <dos.h>
  33. #endif
  34.  
  35. #ifdef unix
  36. #include <sys/time.h>    /* for struct timeval (for select in inputreadyafter) */
  37. #define selectread    /* use select () ? */
  38. #endif
  39.  
  40. #ifdef vms
  41. #include <socket.h>    /* for select () and struct timeval */
  42. # ifdef CURSES
  43. # define _getch_
  44. # endif
  45. #endif
  46.  
  47. #ifdef _getch_
  48. #ifndef CURSES
  49. extern int getch ();
  50. #endif
  51. #endif
  52.  
  53. /*  ==================================================================    *
  54.  *            Unix signalling routines            *
  55.  *  ==================================================================    */
  56.  
  57. void
  58. catch_signals (catch)
  59.   void (* catch) ();
  60. {
  61. #ifdef SIGHUP
  62.   signal (SIGHUP, catch);
  63. #endif
  64. #ifdef SIGILL
  65.   signal (SIGILL, catch);
  66. #endif
  67. #ifdef SIGTRAP
  68.   signal (SIGTRAP, catch);
  69. #endif
  70. #ifdef SIGABRT
  71.   signal (SIGABRT, catch);
  72. #endif
  73. #ifdef SIGEMT
  74.   signal (SIGEMT, catch);
  75. #endif
  76. #ifdef SIGFPE
  77.   signal (SIGFPE, catch);
  78. #endif
  79. #ifdef SIGBUS
  80.   signal (SIGBUS, catch);
  81. #endif
  82. #ifdef SIGSEGV
  83.   signal (SIGSEGV, catch);
  84. #endif
  85. #ifdef SIGSYS
  86.   signal (SIGSYS, catch);
  87. #endif
  88. #ifdef SIGPIPE
  89.   signal (SIGPIPE, catch);
  90. #endif
  91. #ifdef SIGALRM
  92.   signal (SIGALRM, catch);
  93. #endif
  94. #ifdef SIGTERM
  95.   signal (SIGTERM, catch);
  96. #endif
  97. #ifdef SIGXCPU
  98.   signal (SIGXCPU, catch);
  99. #endif
  100. #ifdef SIGXFSZ
  101.   signal (SIGXFSZ, catch);
  102. #endif
  103. #ifdef SIGVTALRM
  104.   signal (SIGVTALRM, catch);
  105. #endif
  106. #ifdef SIGPROF
  107.   signal (SIGPROF, catch);
  108. #endif
  109. #ifdef SIGLOST
  110.   signal (SIGLOST, catch);
  111. #endif
  112. #ifdef SIGUSR1
  113.   signal (SIGUSR1, catch);
  114. #endif
  115. #ifdef SIGUSR2
  116.   signal (SIGUSR2, catch);
  117. #endif
  118. #ifdef SIGUSR3
  119.   signal (SIGUSR3, catch);
  120. #endif
  121. }
  122.  
  123. #ifdef SIGTSTP
  124. void
  125. suspendmyself ()
  126. {
  127.   kill (getpid (), SIGTSTP);
  128. }
  129. FLAG cansuspendmyself = TRUE;
  130. #else
  131. void
  132. suspendmyself ()
  133. {}
  134. FLAG cansuspendmyself = FALSE;
  135. #endif
  136.  
  137. #ifdef SIGWINCH
  138. /*
  139.  * Catch the SIGWINCH signal sent to mined.
  140.  */
  141. void
  142. catchwinch ()
  143. {
  144.   winchg = TRUE;
  145. /*  if (waitingforinput == TRUE) RDwin (); */
  146. /* This is now performed in __readchar () to prevent display garbage 
  147.    in case this interrupts occurs during display output operations which 
  148.    get screen size related values changed while relying on them. */
  149.   signal (SIGWINCH, catchwinch); /* Re-installation of the signal */
  150. }
  151. #endif
  152.  
  153. #ifdef SIGQUIT
  154. /*
  155.  * Catch the SIGQUIT signal (^\) sent to mined. It turns on the quitflag.
  156.  */
  157. void
  158. catchquit ()
  159. {
  160. #ifdef UNUSED /* Should not be needed with new __readchar () */
  161. /* Was previously needed on SUN but showed bad effects on Iris. */
  162.   static char quitchar = '\0';
  163.   if (waitingforinput == TRUE)
  164.     /* simulate input to enable immediate break also during input */
  165.     ioctl (input_fd, TIOCSTI, & quitchar);
  166. #endif
  167.   quit = TRUE;
  168.   signal (SIGQUIT, catchquit); /* Re-installation of the signal */
  169. }
  170. #endif
  171.  
  172. #ifdef SIGBREAK
  173. /*
  174.  * Catch the SIGBREAK signal (control-Break) and turn on the quitflag.
  175.  */
  176. void
  177. catchbreak ()
  178. {
  179.   quit = TRUE;
  180.   signal (SIGBREAK, catchbreak); /* do we need this ? */
  181. }
  182. #else
  183. # ifdef msdos
  184. int
  185. controlbreak ()
  186. {
  187.   quit = TRUE;
  188.   return 1 /* continue program execution */;
  189. }
  190. # endif
  191. #endif
  192.  
  193. #ifdef SIGINT
  194. /*
  195.  * Catch the SIGINT signal (^C) sent if it cannot be ignored by tty driver
  196.  */
  197. void
  198. catchint ()
  199. {
  200.   intr_char = TRUE;
  201.   signal (SIGINT, catchint); /* Re-installation of the signal */
  202. }
  203. #endif
  204.  
  205. /*  ==================================================================    *
  206.  *            Terminal mode switcher                *
  207.  *  ==================================================================    */
  208.  
  209. /*
  210.  * Set and reset tty into CBREAK or old mode according to argument `state'.
  211.  * It also sets all signal characters (except for ^\) to UNDEF. ^\ is caught.
  212.  */
  213. void
  214. raw_mode (state)
  215.   FLAG state;
  216. {
  217. #ifdef TERMIO
  218.   static struct termios old_termio;
  219.      struct termios new_termio;
  220. #ifdef TCGETS
  221. # define gettermio(fd, iopoi)    ioctl (fd, TCGETS, iopoi);
  222. # ifdef TCSETSW
  223. # define settermio(fd, iopoi)    ioctl (fd, TCSETSW, iopoi);
  224. # else
  225. # define settermio(fd, iopoi)    ioctl (fd, TCSETS, iopoi);
  226. # endif
  227. #else
  228. # define gettermio(fd, iopoi)    tcgetattr (fd, iopoi);
  229. # ifdef TCSADRAIN
  230. # define settermio(fd, iopoi)    tcsetattr (fd, TCSADRAIN, iopoi);
  231. # else
  232. # define settermio(fd, iopoi)    tcsetattr (fd, 0, iopoi);
  233. # endif
  234. #endif
  235. #endif /* TERMIO */
  236.  
  237. #ifdef SGTTY
  238.   static struct sgttyb old_tty;
  239.      struct sgttyb new_tty;
  240.   static int oldlmode;
  241.      int lmode;
  242.   static struct tchars old_tchars;
  243.   static struct ltchars old_ltchars;
  244. #define NDEF '\377'
  245.   static struct tchars new_tchars = {NDEF, QUITCHAR, NDEF, NDEF, NDEF, NDEF};
  246.   static struct tchars new_QStchars = {NDEF, QUITCHAR, '\021', '\023', NDEF, NDEF};
  247.   static struct ltchars new_ltchars = {NDEF, NDEF, NDEF, NDEF, NDEF, NDEF};
  248. /* correspondence between the tchars/ltchars characters of the sgtty 
  249.    interface and the c_cc characters of the termios interface (codes vary):
  250.     sgtty        termio        sgtty        termio
  251.     t_intrc        VINTR        t_suspc        VSUSP
  252.     t_quitc        VQUIT        t_dsuspc    VDSUSP
  253.     t_startc    VSTART        t_rprntc    VREPRINT
  254.     t_stopc        VSTOP        t_flushc    VDISCARD
  255.     t_eofc        VEOF (VMIN)    t_werasc    VWERASE
  256.     t_brkc        VEOL (VTIME)    t_lnextc    VLNEXT
  257. */
  258. #endif /* SGTTY */
  259.  
  260.   if (state == OFF) {
  261.     isscreenmode = FALSE;
  262. #ifdef CURSES
  263.     endwin ();
  264. #ifdef vms
  265.     system ("set terminal /ttsync /nopasthru");
  266. #endif
  267. #else /* ndef CURSES: */
  268.     end_screen_mode ();
  269.     flush ();
  270. #endif /* ndef CURSES */
  271.  
  272. #ifdef TERMIO
  273.     settermio (input_fd, & old_termio);
  274. #endif
  275. #ifdef SGTTY
  276.     ioctl (input_fd, TIOCSETP, & old_tty);
  277.     ioctl (input_fd, TIOCSETC, & old_tchars);
  278.     ioctl (input_fd, TIOCSLTC, & old_ltchars);
  279.     ioctl (input_fd, TIOCLSET, & oldlmode);
  280. #endif
  281.     return;
  282.   }
  283.  
  284.   else /* (state == ON) */ {
  285.     isscreenmode = TRUE;
  286. #ifdef CURSES
  287.     refresh ();
  288. #else
  289.     start_screen_mode ();
  290.     flush ();
  291. #endif
  292. #ifdef TERMIO
  293.     gettermio (input_fd, & old_termio);
  294.     gettermio (input_fd, & new_termio);
  295.  
  296.     if (controlQS == FALSE)
  297.       new_termio.c_iflag &= ~(ISTRIP|IXON|IXOFF);
  298.     else
  299.       new_termio.c_iflag &= ~(ISTRIP);
  300.     new_termio.c_oflag &= ~OPOST;
  301.     new_termio.c_cflag &= ~(PARENB|CSIZE);
  302.     new_termio.c_cflag |= CS8;
  303.     new_termio.c_lflag &= ~(ICANON|ECHO);
  304. #define NDEF '\000'
  305.     new_termio.c_cc [VMIN] = 1;
  306.     new_termio.c_cc [VTIME] = 0;
  307.     new_termio.c_cc [VQUIT] = QUITCHAR;
  308.     new_termio.c_cc [VINTR] = NDEF;
  309.     new_termio.c_cc [VSUSP] = NDEF;
  310. #ifdef VDISCARD
  311.     new_termio.c_cc [VDISCARD] = NDEF;
  312. #endif
  313.     settermio (input_fd, & new_termio);
  314. #endif /* TERMIO */
  315. #ifdef SGTTY
  316. /* Save old tty settings */
  317.     ioctl (input_fd, TIOCGETP, & old_tty);
  318.     ioctl (input_fd, TIOCGETC, & old_tchars);
  319.     ioctl (input_fd, TIOCGLTC, & old_ltchars);
  320.     ioctl (input_fd, TIOCLGET, & oldlmode);
  321. /* Set line mode */
  322. /* If this feature should not be available on some system, RAW must be used
  323.    instead of CBREAK below to enable 8 bit characters on output */
  324.     lmode = oldlmode;
  325.     lmode |= LPASS8; /* enable 8 bit characters on input in CBREAK mode */
  326.     lmode |= LLITOUT; /* enable 8 bit characters on output in CBREAK mode;
  327.         this may not be necessary in newer Unixes, e.g. SUN-OS 4;
  328.         output handling is slightly complicated by LITOUT */
  329.     ioctl (input_fd, TIOCLSET, & lmode);
  330. /* Set tty to CBREAK (or RAW) mode */
  331.     new_tty = old_tty;
  332.     new_tty.sg_flags &= ~ECHO;
  333.     new_tty.sg_flags |= CBREAK;
  334.     ioctl (input_fd, TIOCSETP, & new_tty);
  335. /* Unset signal chars */
  336.     if (controlQS == FALSE)
  337.       ioctl (input_fd, TIOCSETC, & new_tchars);  /* Only leaves QUITCHAR */
  338.     else
  339.       ioctl (input_fd, TIOCSETC, & new_QStchars);  /* Leaves QUITCHAR, ^Q, ^S */
  340.     ioctl (input_fd, TIOCSLTC, & new_ltchars); /* Leaves nothing */
  341. #endif /* SGTTY */
  342.  
  343. /* Define signal handlers */
  344. #ifdef SIGQUIT
  345.     signal (SIGQUIT, catchquit);    /* Catch QUITCHAR (^\) */
  346. #endif
  347. #ifdef SIGBREAK
  348.     signal (SIGBREAK, catchbreak);    /* control-Break (OS/2) */
  349. #else
  350. # ifdef msdos
  351.     ctrlbrk (controlbreak);    /* completely useless, stupid Turbo-C! */
  352. # endif
  353. #endif
  354. #ifdef SIGINT
  355.     signal (SIGINT, catchint);    /* Catch INTR char (^C) */
  356. #endif
  357. #ifdef SIGWINCH
  358.     signal (SIGWINCH, catchwinch);    /* Catch window size changes */
  359. #endif
  360.   }
  361. }
  362.  
  363. /*  ==================================================================    *
  364.  *            Unix I/O routines                *
  365.  *  ==================================================================    */
  366.  
  367. #ifdef CURSES
  368.  
  369. void
  370. __putchar (c)
  371.   register uchar c;
  372. { addch (c); }
  373.  
  374. void
  375. putstring (str)
  376.   register uchar * str;
  377. { addstr (str); }
  378.  
  379. void
  380. flush ()
  381. { refresh (); }
  382.  
  383. FLAG    can_add_line = TRUE, can_delete_line = TRUE,
  384.     can_scroll_reverse = TRUE, can_clear_eol = TRUE;
  385.  
  386. void
  387. clear_screen ()
  388. {
  389.   clear ();
  390. }
  391. void
  392. clear_eol ()
  393. {
  394.   clrtoeol ();
  395. }
  396. void
  397. scroll_forward ()
  398. {
  399.   scroll (stdscr);
  400. }
  401. void
  402. scroll_reverse ()
  403. { /* only called if cursor is at top of screen */
  404.   insertln ();
  405. }
  406. void
  407. add_line (y)
  408.   register int y;
  409. {
  410.   move (y, 0);
  411.   insertln ();
  412. }
  413. void
  414. delete_line (y)
  415.   register int y;
  416. {
  417.   move (y, 0);
  418.   deleteln ();
  419. }
  420. void
  421. move_cursor (x, y)
  422.   register int x, y;
  423. {
  424.   move (y, x);
  425. }
  426. void
  427. reverse_on ()
  428. {
  429.   standout ();
  430. }
  431. void
  432. reverse_off ()
  433. {
  434.   standend ();
  435. }
  436.  
  437. void
  438. get_term_cap (TERMname)
  439.   char * TERMname;
  440. {
  441. #ifdef vms
  442.   system ("set terminal /pasthru /nottsync");
  443. #endif
  444.   initscr ();
  445. #ifdef vms
  446.   crmode ();
  447. #else
  448.   crmode (); /* cbreak (); */
  449.   nonl ();
  450. #endif
  451.   noecho ();
  452.   scrollok (stdscr, TRUE);
  453. #ifdef unix
  454. #ifndef vax
  455.   idlok (stdscr, TRUE);
  456. #ifndef sun
  457.   typeahead (input_fd);
  458. #endif
  459. #endif
  460. #endif
  461.  
  462.   YMAX = LINES - 1;    /* # of lines */
  463.   XMAX = COLS - 1;    /* # of columns */
  464.   getwinsize ();
  465. }
  466.  
  467. /*------------------------------------------------------------------------*/
  468. #else    /* ndef CURSES: */
  469.  
  470. void
  471. __putchar (c)
  472.   register uchar c;
  473. { writechar (output_fd, (c)); }
  474.  
  475. void
  476. putstring (str)
  477.   register uchar * str;
  478. { (void) writestring (output_fd, (str)); }
  479.  
  480. void
  481. flush ()
  482. { (void) flush_buffer (output_fd); }
  483.  
  484. #ifdef unix
  485.  
  486. extern int tgetent ();
  487. extern char * tgetstr ();
  488. extern int tgetnum ();
  489. extern char * tgoto ();
  490. extern int tputs ();
  491. #define termputstr(str, aff)    (void) tputs (str, aff, (intfunc) __putchar)
  492.  
  493. /* Storage for the terminal control sequences */
  494. char *cCL, *cCE, *cSR, *cAL, *cDL, *cCS, *cSC, *cRC,
  495.      *cCM, *cSO, *cSE, *cVS, *cVE, *cTI, *cTE;
  496. #define aff1 0
  497. #define affmax YMAX
  498.  
  499. FLAG    can_add_line = FALSE, can_delete_line = FALSE,
  500.     can_scroll_reverse = FALSE, can_clear_eol = FALSE;
  501.  
  502. void
  503. clear_screen ()
  504. {
  505.   termputstr (cCL, affmax);
  506. }
  507. void
  508. clear_eol ()
  509. {
  510.   if (can_clear_eol == TRUE) termputstr (cCE, aff1);
  511. }
  512. void
  513. scroll_forward ()
  514. {
  515.   move_cursor (0, YMAX);
  516. /*  putchar ('\n');    */
  517.   termputstr ("\n", affmax);
  518. }
  519. void
  520. scroll_reverse ()
  521. {
  522.   termputstr (cSR, affmax);
  523. }
  524. void
  525. add_line (y)
  526.   register int y;
  527. {
  528.   if (cAL) {
  529.     move_cursor (0, y);
  530.     termputstr (cAL, affmax);
  531.   }
  532.   else {
  533.     move_cursor (0, y);
  534.     termputstr (cSC, aff1);
  535.     termputstr (tgoto (cCS, YMAX, y), aff1);
  536.     termputstr (cRC, aff1);
  537.     termputstr (cSR, affmax);
  538.     termputstr (tgoto (cCS, YMAX, 0), aff1);
  539.     termputstr (cRC, aff1);
  540.   }
  541. }
  542. void
  543. delete_line (y)
  544.   register int y;
  545. {
  546.   if (cDL) {
  547.     move_cursor (0, y);
  548.     termputstr (cDL, affmax);
  549.   }
  550.   else {
  551.     move_cursor (0, y);
  552.     termputstr (cSC, aff1);
  553.     termputstr (tgoto (cCS, YMAX, y), aff1);
  554.     move_cursor (0, YMAX);
  555. /*    putchar ('\n');    */
  556.     termputstr ("\n", affmax);
  557.     termputstr (tgoto (cCS, YMAX, 0), aff1);
  558.     termputstr (cRC, aff1);
  559.   }
  560. }
  561. void
  562. move_cursor (x, y)
  563.   register int x, y;
  564. {
  565.   termputstr (tgoto (cCM, x, y), aff1);
  566. }
  567. void
  568. reverse_on ()
  569. {
  570.   termputstr (cSO, aff1);
  571. }
  572. void
  573. reverse_off ()
  574. {
  575.   termputstr (cSE, aff1);
  576. }
  577. void
  578. start_screen_mode ()
  579. {
  580.   termputstr (cTI, affmax);
  581.   termputstr (cVS, affmax);
  582. /* Install correct scrolling region in case terminal is bigger than assumed */
  583. /* (this effect was observed after window size changes of Sun windows): */
  584.   if (cCS) termputstr (tgoto (cCS, YMAX, 0), aff1);
  585. }
  586. void
  587. end_screen_mode ()
  588. {
  589.   termputstr (cTE, affmax);
  590.   termputstr (cVE, affmax);
  591. }
  592.  
  593. void
  594. get_term_cap (TERMname)
  595.   char * TERMname;
  596. {
  597. #define termbuflen 100
  598.   char entry [1024];
  599.   static char termbuf [termbuflen];
  600.   char * loc = termbuf;
  601.  
  602.   if (tgetent (entry, TERMname) <= 0) {
  603.     panic ("Unknown terminal", NIL_PTR);
  604.   }
  605.  
  606.   YMAX = tgetnum ("li" /*, & loc */) - 1;    /* # of lines */
  607.   XMAX = tgetnum ("co" /*, & loc */) - 1;    /* # of columns */
  608. /* getenv ("LINES"), getenv ("COLUMNS") ?! */
  609.   getwinsize ();
  610.  
  611.   cCL = tgetstr ("cl", & loc);    /* clear screen */
  612.   cCE = tgetstr ("ce", & loc);    /* clear to end of line */
  613.   cSR = tgetstr ("sr", & loc);    /* scroll reverse */
  614.   cAL = tgetstr ("al", & loc);    /* add line */
  615.   if (!cSR) cSR = cAL;
  616.   cDL = tgetstr ("dl", & loc);    /* delete line */
  617.   cCS = tgetstr ("cs", & loc);    /* change scrolling region */
  618.   cSC = tgetstr ("sc", & loc);    /* save cursor    \ needed with vt100   */
  619.   cRC = tgetstr ("rc", & loc);    /* restore cursor / for add/delete line */
  620.   cCM = tgetstr ("cm", & loc);    /* cursor motion */
  621.   cSO = tgetstr ("so", & loc);    /* stand out mode */
  622.   cSE = tgetstr ("se", & loc);    /* end " */
  623.   cVS = tgetstr ("vs", & loc);    /* visual mode */
  624.   cVE = tgetstr ("ve", & loc);    /* end " */
  625.   cTI = tgetstr ("ti", & loc);    /* positioning mode */
  626.   cTE = tgetstr ("te", & loc);    /* end " */
  627.  
  628.   if (cAL || (cSR && cCS)) can_add_line = TRUE;
  629.   if (cSR) can_scroll_reverse = TRUE;
  630.   if (cDL || cCS) can_delete_line = TRUE;
  631.   if (cCE) can_clear_eol = TRUE;
  632.  
  633.   if (loc > termbuf + termbuflen) {
  634.     panic ("Terminal control strings don't fit", NIL_PTR);
  635.   }
  636.   if (!cCL || !cCM || !cSR || !cCE /* || !cSO || !cSE */ ) {
  637.     panic ("Sorry, no mined on this type of terminal", NIL_PTR);
  638.   }
  639. }
  640.  
  641. /*------------------------------------------------------------------------*/
  642. #endif /* unix */
  643.  
  644. #ifdef msdos
  645.  
  646. /*
  647.  * checkwin checks if a screen size change has occurred
  648.     BIOS data:
  649.     40:4A    word    video columns
  650.     can also be determined with INT10h, function 0Fh
  651.     40:84    byte    video lines - 1            (EGA/VGA required)
  652.     40:85    word    character height (pixels)    (EGA/VGA required)
  653.     can also be determined with INT10h, function 11h/30h
  654.  */
  655. int
  656. checkwin ()
  657. {
  658.   return peek (0x40, 0x4A) != XMAX + 1
  659. /* the following line requires EGA or VGA: */
  660.       || peekb (0x40, 0x84) != YMAX
  661.     ;
  662. }
  663.  
  664. /*
  665.  * getch () reads in a character from keyboard. We seem to need our 
  666.  * own low-level input routine since (at least with Turbo-C) the use 
  667.  * of getch () from conio.h makes the runtime system switch to normal 
  668.  * text mode on startup so that extended text modes could not be used.
  669.  * This is really a very stupid chicane of Turbo-C.
  670.  */
  671. int wincheck = 1;
  672. int
  673. getch ()
  674. { union REGS Regs;
  675.   int result;
  676.  
  677.   Regs.h.ah = 0x07;
  678.   intdos (& Regs, & Regs);
  679.   result = Regs.h.al;
  680.  
  681.   if (wincheck && checkwin ()) {
  682.     winchg = TRUE;
  683.   /* in MSDOS, RDwin calls getch, so it cannot be called directly here */
  684.   }
  685.  
  686.   return result;
  687. }
  688.  
  689. void
  690. set_video_lines (r)
  691. /* 0/1/2: 200/350/400 lines */
  692.   int r;
  693. {
  694.   union REGS Regs;
  695.  
  696.   Regs.h.ah = 0x12;
  697.   Regs.h.bl = 0x30;
  698.   Regs.h.al = r;
  699.  
  700.   int86 (0x10, & Regs, & Regs);
  701. }
  702.  
  703. int font_height = 16;
  704. void
  705. set_font_height (r)
  706. /* set font height in character pixels, <= 32 */
  707.   int r;
  708. {
  709. #define useintr
  710. #ifdef useintr
  711.   struct REGPACK Regs;
  712.  
  713.   Regs.r_ax = 0x1130;
  714.   Regs.r_bx = 0;
  715.   intr (0x10, & Regs);
  716.   Regs.r_ax = 0x1110;
  717.   Regs.r_bx = r << 8;
  718.   Regs.r_cx = 256;
  719.   Regs.r_dx = 0;
  720. /*
  721.   Regs.r_bp = 0;
  722.   Regs.r_es = 0;
  723. */
  724.   intr (0x10, & Regs);
  725. #else
  726.   union REGS Regs;
  727.  
  728.   Regs.h.ah = 0x11;
  729.   Regs.h.al = 0x10;
  730.   Regs.h.bh = r;
  731.   font_height = r;
  732.   Regs.h.bl = 0;
  733.   Regs.x.cx = 256;
  734.   Regs.x.dx = 0;
  735. /*  Regs.x.bp = 0;    ignored by Turbo-C's int86 function */
  736. /*  Regs.x.es = 0;    not in structure but accepted by rotten C */
  737.   int86 (0x10, & Regs, & Regs);
  738. #endif
  739. }
  740.  
  741. void
  742. set_grafmode_height (r, l)
  743. /* 0/1/2: font height 8/14/16 ; 1/2/3/n: 14/25/43/n lines */
  744.   int r, l;
  745. {
  746.   union REGS Regs;
  747.  
  748.   Regs.h.ah = 0x11;
  749.   if (r == 0) Regs.h.al = 0x23;
  750.   else if (r == 1) Regs.h.al = 0x22;
  751.   else Regs.h.al = 0x24;
  752.   if (l <= 0) Regs.h.bl = 1;
  753.   else if (l <= 3) Regs.h.bl = l;
  754.   else {
  755.     Regs.h.bl = 0;
  756.     Regs.h.dl = l;
  757.   }
  758.  
  759.   int86 (0x10, & Regs, & Regs);
  760. }
  761.  
  762. void
  763. set_fontbank (f)
  764. /* 0..7 */
  765.   int f;
  766. {
  767.   union REGS Regs;
  768.  
  769.   Regs.h.ah = 0x11;
  770.   Regs.h.al = 0x03;
  771.   Regs.h.bl = (f & 3) * 5 + (f & 4) * 12;
  772.  
  773.   int86 (0x10, & Regs, & Regs);
  774. }
  775.  
  776. #ifdef conio
  777. #include <conio.h>
  778.  
  779. FLAG    can_add_line = TRUE, can_delete_line = TRUE,
  780.     can_scroll_reverse = TRUE, can_clear_eol = TRUE;
  781.  
  782. void
  783. clear_screen ()
  784. { clrscr (); }
  785. void
  786. clear_eol ()
  787. { clreol (); }
  788. void
  789. scroll_forward ()
  790. {
  791.   move_cursor (0, YMAX);
  792.   putchar ('\n');
  793. }
  794. void
  795. scroll_reverse ()
  796. { /* only called if cursor is at top of screen */
  797.   insline ();
  798. }
  799. void
  800. add_line (y)
  801.   register int y;
  802. {
  803.   move_cursor (0, y);
  804.   insline ();
  805. }
  806. void
  807. delete_line (y)
  808.   register int y;
  809. {
  810.   move_cursor (0, y);
  811.   delline ();
  812. }
  813. void
  814. move_cursor (x, y)
  815. {
  816.   gotoxy (x + 1, y + 1);
  817. }
  818. void
  819. reverse_on ()
  820. { highvideo ();
  821. }
  822. void
  823. reverse_off ()
  824. { normvideo ();
  825. }
  826. void
  827. start_screen_mode ()
  828. {}
  829. void
  830. end_screen_mode ()
  831. {}
  832.  
  833. void
  834. get_term ()
  835. {
  836.   getwinsize ();
  837. }
  838.  
  839. void
  840. getwinsize ()
  841. {
  842. /* this has to be extended to request the current screen size */
  843.   struct text_info scrinfo;
  844.  
  845.   gettextinfo (& scrinfo);
  846.   /* This seems to be a junk procedure since no other information than
  847.      25 * 80 comes out in 50 lines mode */
  848.   YMAX = scrinfo.screenheight - 1;
  849.   XMAX = scrinfo.screenwidth - 1;
  850. }
  851.  
  852. #else /* ndef conio - use ANSI driver: */
  853.  
  854. /* adjust the following values to the capabilities of your ANSI driver: */
  855. FLAG    can_add_line = TRUE, can_delete_line = TRUE,
  856.     can_scroll_reverse = TRUE, can_clear_eol = TRUE;
  857.  
  858. char CUP1 [] = "\033[1;1H";
  859. char CUD1 [] = "\033[B";
  860. char CUF1 [] = "\033[C";
  861. char DSR [] = "\033[6n";
  862. char ED2 [] = "\033[2J";
  863. char EL [] = "\033[K";
  864. char IL1 [] = "\033[L";
  865. char DL1 [] = "\033[M";
  866.  
  867. void
  868. clear_screen ()
  869. { putstring (ED2); }
  870. void
  871. clear_eol ()
  872. {
  873.   if (can_clear_eol == TRUE) putstring (EL);
  874. }
  875. void
  876. scroll_forward ()
  877. {
  878.   move_cursor (0, YMAX);
  879.   putchar ('\n');
  880. }
  881. void
  882. scroll_reverse ()
  883. { /* only called if cursor is at top of screen */
  884.   putstring (IL1);
  885. }
  886. void
  887. add_line (y)
  888.   register int y;
  889. {
  890.   move_cursor (0, y);
  891.   putstring (IL1);
  892. }
  893. void
  894. delete_line (y)
  895.   register int y;
  896. {
  897.   move_cursor (0, y);
  898.   putstring (DL1);
  899. }
  900. void
  901. move_cursor (x, y)
  902.   register int x, y;
  903. { static char s [11];
  904.   build_string (s, "\033[%d;%dH", y + 1, x + 1);
  905.   putstring (s);
  906. }
  907. char reverse_on_str [30] = "\033[7m";    /* inverse mode */
  908. char reverse_off_str [30] = "\033[27m";    /* inverse off */
  909. void
  910. reverse_on ()
  911. { putstring (reverse_on_str); /* 1m | 7m | 7m    | 7;2m */
  912. }
  913. void
  914. reverse_off ()
  915. { putstring (reverse_off_str); /* m  | 0m | 0m 1m | m    */
  916. }
  917. void
  918. start_screen_mode ()
  919. {}
  920. void
  921. end_screen_mode ()
  922. {}
  923.  
  924. FLAG noCPR = FALSE;
  925.  
  926. int
  927. getANSIpos ()
  928. /* returns FALSE if indicated position is upper left corner */
  929. /* also leaves position in XMAX+1, YMAX+1 */
  930. /* Checks characters input against ANSI CPR (cursor position report) 
  931.    sequence. If it does not comply, sets noCPR flag, does not check again
  932.    and reports as if cursor had been moved. By this trick, we implement 
  933.    the following auxiliary behaviour: If an ANSI driver cannot deliver 
  934.    cursor reports, mined may be stuffed the screen size as its first input, 
  935.    at the positions of an ANSI CPR sequence but embedded in different 
  936.    characters, e.g. xx25x80xx */
  937. {
  938.   if (noCPR == TRUE) return 1;
  939.   wincheck = 0;    /* prevent recursive calls of checkwin and getANSIpos */
  940.   putstring (DSR);
  941.   flush ();
  942.   if (readchar () != '\033') noCPR = TRUE;
  943.   if (readchar () != '[') noCPR = TRUE;
  944.   if (get_digits (& YMAX) != ';') noCPR = TRUE;
  945.   if (get_digits (& XMAX) != 'R') noCPR = TRUE;
  946.   (void) readchar ();    /* MSDOS ANSI drivers send a final return */
  947.   YMAX = YMAX - 1; XMAX = XMAX - 1;
  948.   wincheck = 1;
  949.   return YMAX != 0 || XMAX != 0;
  950. }
  951.  
  952. int
  953. failANSI (check)
  954. /* returns FALSE if control string does not change screen position */
  955.   char * check;
  956. {
  957.   putstring (CUP1);
  958.   putstring (check);
  959.   return getANSIpos ();
  960. }
  961.  
  962. void
  963. get_term ()
  964. {
  965.   char * colstr = unnull (getenv ("MINEDCOL"));
  966.   char * colrev = colstr;
  967.   while (* colrev != '\0' && * colrev != ' ') colrev ++;
  968.   if (* colrev == ' ') {* colrev = '\0'; colrev ++;}
  969.  
  970. /* first do some harmless checks to set noCPR if simple ANSI driver */
  971. /* if (failANSI (EL)) can_clear_eol = FALSE; probably every driver can do this */
  972.   if (failANSI (DL1)) can_delete_line = FALSE;
  973.   if (failANSI (IL1)) {
  974.     can_add_line = FALSE;
  975.     can_scroll_reverse = FALSE;
  976.   }
  977.  
  978. /* heuristics: if driver cannot delete line we assume if can neither set 
  979.    extended attributes like our default inverse and inverse off,
  980.    so change the default */
  981.   if (can_delete_line == FALSE) {
  982.     build_string (reverse_off_str, "\033[32;40m");
  983.     build_string (reverse_on_str, "\033[30;42m");
  984.   }
  985.  
  986. /* if MINEDCOL set, use it for display attributes instead of defaults */
  987.   if (* colstr != '\0') build_string (reverse_off_str, "\033[%sm", colstr);
  988.   if (* colrev != '\0') build_string (reverse_on_str, "\033[%sm", colrev);
  989.  
  990. /* if cursor reports are available, check display attribute strings */
  991.   if (noCPR == FALSE) {
  992.     if (failANSI (reverse_on_str)) panic ("Invalid control sequence for exposed display", NIL_PTR);
  993.     if (failANSI (reverse_off_str)) panic ("Invalid control sequence for normal display", NIL_PTR);
  994.   }
  995.  
  996.   getwinsize ();
  997. }
  998.  
  999. void
  1000. getwinsize ()
  1001. {
  1002. #define stepcur 9
  1003.   int oldx = -1; int oldy = -1;
  1004.   int i;
  1005.   if (noCPR == FALSE) {
  1006.     putstring (CUP1);
  1007.     XMAX = 0; YMAX = 0;
  1008.     do {
  1009.         for (i = 0; i < stepcur; i ++) {
  1010.             if (oldx < XMAX) putstring (CUF1);
  1011.             if (oldy < YMAX) putstring (CUD1);
  1012.         }
  1013.         oldx = XMAX + (stepcur - 1);
  1014.         oldy = YMAX + (stepcur - 1);
  1015.         (void) getANSIpos ();
  1016.     } while (oldx < XMAX || oldy < YMAX);
  1017.   }
  1018.   if (getenv ("LINES")) {make_number (& YMAX, getenv ("LINES")); YMAX --;}
  1019.   if (getenv ("COLUMNS")) {make_number (& XMAX, getenv ("COLUMNS")); XMAX --;}
  1020.   if (getenv ("NOCLEAREOL")) can_clear_eol = FALSE;    /* for debugging */
  1021. /*  move_cursor (999, 999); */
  1022. /*  (void) getANSIpos (); */
  1023. }
  1024.  
  1025. #endif /* ndef conio */
  1026. #endif /* def msdos */
  1027.  
  1028. /****************************************************************************
  1029.  * screen mode setting functions, alternatively by MSDOS BIOS calls or 
  1030.  * ANSI sequences
  1031.  */
  1032.  
  1033. int textmode_height = 2;
  1034.  
  1035. #ifdef msdos
  1036.  
  1037. void
  1038. set_screen_mode (m)
  1039.   int m;
  1040. {
  1041.   union REGS Regs;
  1042.  
  1043.   if (m >= 0) {
  1044.     Regs.h.ah = 0x00;
  1045.     Regs.h.al = m;
  1046.     int86 (0x10, & Regs, & Regs);
  1047.   }
  1048. }
  1049.  
  1050. void
  1051. set_textmode_height (r)
  1052. /* 0/1/2: font height 8/14/16 */
  1053.   int r;
  1054. {
  1055.   union REGS Regs;
  1056.  
  1057.   Regs.h.ah = 0x11;
  1058.   Regs.h.bl = 0;
  1059.   textmode_height = r;
  1060.   if (r == 0) Regs.h.al = 0x12;
  1061.   else if (r == 1) Regs.h.al = 0x11;
  1062.   else Regs.h.al = 0x14;
  1063.  
  1064.   int86 (0x10, & Regs, & Regs);
  1065. }
  1066.  
  1067. #else /* ndef msdos - use ANSI driver: */
  1068.  
  1069. int screen_mode = 3    /* just an assumption, cannot be determined */;
  1070.  
  1071. void
  1072. set_screen_mode (m)
  1073.   int m;
  1074. {
  1075.   char resize_str [8];
  1076.  
  1077.   if (m >= 0) {
  1078.     if (m != 50 && m != 43) screen_mode = m;
  1079.     build_string (resize_str, "\033[=%dh", m);
  1080.     putstring (resize_str);
  1081.   }
  1082. }
  1083.  
  1084. void
  1085. set_textmode_height (r)
  1086. /* 0/1/2: font height 8/14/16 */
  1087.   int r;
  1088. {
  1089.   textmode_height = r;
  1090.   if (r == 0) set_screen_mode (50);
  1091.   else if (r == 1) set_screen_mode (43);
  1092.   else set_screen_mode (screen_mode);
  1093. }
  1094.  
  1095. #endif
  1096.  
  1097. void
  1098. switch_textmode_height (cycle)
  1099. /* TRUE: cycle through font heights 8/14/16 
  1100.    FALSE: switch between font heights 8/16 */
  1101.   FLAG cycle;
  1102. {
  1103.   if (textmode_height >= 2) set_textmode_height (0);
  1104.   else if (cycle == TRUE) set_textmode_height (textmode_height + 1);
  1105.   else set_textmode_height (2);
  1106. }
  1107.  
  1108. extern
  1109. struct {
  1110.     int mode, cols, lins;
  1111. } modetab [] /* in minedmp.c together with other configurable stuff */;
  1112.  
  1113. void
  1114. resize_screen (sb, keep_columns)
  1115.   FLAG sb, keep_columns;
  1116. {
  1117. /*  char resize_str [8]; */
  1118.   int totalchars = (XMAX + 1) * (YMAX + 1);
  1119.   int newtotal = 0;
  1120.   int curtotal;
  1121.   int newmode = -1;
  1122.   int i;
  1123.  
  1124.   if (keep_columns == TRUE && ((sb == SMALLER && textmode_height > 0)
  1125.                 || (sb == BIGGER && textmode_height < 2)))
  1126.   {
  1127.     if (sb == SMALLER)
  1128.         set_textmode_height (textmode_height - 1);
  1129.     else    set_textmode_height (textmode_height + 1);
  1130.   }
  1131.   else
  1132.   {
  1133.      i = 0;
  1134.      while (modetab [i].mode >= 0) {
  1135.     curtotal = modetab [i].cols * modetab [i].lins;
  1136.     if (((sb == SMALLER && curtotal < totalchars && curtotal > newtotal) ||
  1137.          (sb == BIGGER && curtotal > totalchars && (newtotal == 0 || curtotal < newtotal)))
  1138.         && (keep_columns == FALSE || modetab [i].cols == XMAX + 1))
  1139.     {    newtotal = curtotal;
  1140.         newmode = modetab [i].mode;
  1141.     }
  1142.     i ++;
  1143.      }
  1144.      if (newmode >= 0) {
  1145.     set_screen_mode (newmode);
  1146.     if (keep_columns == TRUE)
  1147.         if (sb == BIGGER)
  1148.             set_textmode_height (0);
  1149.         else    set_textmode_height (2);
  1150.      }
  1151.   }
  1152. }
  1153.  
  1154. #endif /* ndef CURSES */
  1155.  
  1156. /*------------------------------------------------------------------------*/
  1157.  
  1158. /*
  1159.  * Read a character from the operating system and handle interrupts.
  1160.  * Concerning problems due to the interference of read operations and
  1161.  * incoming signals (QUIT, WINCH) see the comments at readchar ().
  1162.  */
  1163. int
  1164. strange (err)
  1165.   char * err;
  1166. {
  1167.   ring_bell ();
  1168.   error ("Read interrupted: ", err);
  1169.   sleep (1);
  1170.   ring_bell ();
  1171.   return QUITCHAR;
  1172. }
  1173.  
  1174. /*
  1175.  * Is a character available within msec milliseconds from file no fid?
  1176.  */
  1177. int
  1178. inputreadyafter (fid, msec)
  1179.   int fid;
  1180.   int msec;
  1181. {
  1182. #ifdef selectread
  1183.   int readfds;
  1184.   static struct timeval timeoutstru = {0, 0};
  1185.   register int nfds;
  1186.  
  1187.   readfds = 1 << fid;
  1188.   timeoutstru.tv_usec = 1000 * msec;
  1189.   nfds = select (fid + 1, & readfds, 0, 0, & timeoutstru);
  1190.   return nfds;
  1191. #else
  1192.   if (msec < 500)
  1193.     return 1;
  1194.   else    return fid - fid;
  1195. #endif
  1196. }
  1197.  
  1198. /*
  1199.  * Read a char from operating system, handle interrupts if possible, 
  1200.  * handle window size changes if possible.
  1201.  */
  1202. #ifdef selectread
  1203. int
  1204. __readchar ()
  1205. {
  1206.   uchar c;
  1207.   register int n;
  1208.   int readfds, exceptfds;
  1209.  
  1210.   do {
  1211.     if (winchg == TRUE) RDwin ();
  1212.     readfds = 1 << input_fd;
  1213.     exceptfds = readfds;
  1214.     select (input_fd + 1, & readfds, 0, & exceptfds, 0);
  1215.     if (exceptfds) {
  1216.        if (quit == TRUE) return QUITCHAR;
  1217.        else if (winchg == TRUE) ;
  1218.        else if (intr_char == TRUE) {intr_char = FALSE; return '\003';}
  1219.        else return strange ("exception");
  1220.     }
  1221.     else
  1222. #ifdef _getch_
  1223.        return getch ();
  1224. #else
  1225.     {
  1226.        if ((n = read (input_fd, & c, 1)) == 1) return c;
  1227.        else if ((n == 0) || (geterrno () != EINTR))
  1228.         panicio ("Error during character input", serror ());
  1229.        else return strange (serror ());
  1230.     }
  1231. #endif
  1232.   } while (TRUE);
  1233. }
  1234. #else
  1235. int
  1236. __readchar ()
  1237. {
  1238.   uchar c;
  1239.  
  1240. #ifdef _getch_
  1241.   c = getch ();
  1242.   if (intr_char == TRUE) {intr_char = FALSE; c = '\003';}
  1243. #else
  1244.   if (read (input_fd, & c, 1) != 1 && quit == FALSE) {
  1245.     if (geterrno () == EINTR) return __readchar ();
  1246.     else panicio ("Error during character input", serror ());
  1247.   }
  1248. #endif
  1249.   if (quit == TRUE) c = QUITCHAR;
  1250.   return c;
  1251. }
  1252. #endif
  1253.  
  1254. /*------------------------------------------------------------------------*/
  1255.  
  1256. #ifdef vms
  1257.  
  1258. void
  1259. get_term ()
  1260. {
  1261.   get_term_cap (NIL_PTR);
  1262. }
  1263.  
  1264. void
  1265. getwinsize ()
  1266. {
  1267. /* Can this be determined on VMS? Any advise by someone? */
  1268. }
  1269.  
  1270. #endif /* vms */
  1271.  
  1272. #ifdef unix
  1273.  
  1274. /*
  1275.  * Get current window size
  1276.  */
  1277. void
  1278. getwinsize ()
  1279. {
  1280. #ifdef TIOCGWINSZ
  1281.   struct winsize winsiz;
  1282.  
  1283.   ioctl (output_fd, TIOCGWINSZ, & winsiz);
  1284.   if (winsiz.ws_row != 0) YMAX = winsiz.ws_row - 1;
  1285.   if (winsiz.ws_col != 0) XMAX = winsiz.ws_col - 1;
  1286. #else
  1287. #ifdef TIOCGSIZE
  1288.   struct ttysize ttysiz;
  1289.  
  1290.   ioctl (output_fd, TIOCGSIZE, & ttysiz);
  1291.   if (ttysiz.ts_lines != 0) YMAX = ttysiz.ts_lines - 1;
  1292.   if (ttysiz.ts_cols != 0) XMAX = ttysiz.ts_cols - 1;
  1293. #else
  1294. #ifdef WIOCGETD
  1295.   struct uwdata uwdat;
  1296.  
  1297.   ioctl (output_fd, WIOCGETD, & uwdat);
  1298.   if (uwdat.uw_height > 0) YMAX = uwdat.uw_height / uwdat.uw_vs - 1;
  1299.   if (uwdat.uw_width > 0) XMAX = uwdat.uw_width / uwdat.uw_hs - 1;
  1300. #else
  1301. /* Who can tell me how to do this on different systems? */
  1302. #endif
  1303. #endif
  1304. #endif
  1305. }
  1306.  
  1307. /*
  1308.  * Get terminal information
  1309.  */
  1310. void
  1311. get_term ()
  1312. {
  1313.   char * TERMname = getenv ("TERM");
  1314.  
  1315.   if (TERMname == NIL_PTR)
  1316.     panic ("Terminal not specified", NIL_PTR);
  1317.  
  1318.   get_term_cap (TERMname);
  1319.  
  1320. /* build_string (text_buffer, "Terminal is %s, %d * %d.\n", TERMname, YMAX+1, XMAX+1);
  1321.   putstring (text_buffer); */
  1322. }
  1323.  
  1324. #endif /* unix */
  1325.  
  1326. /*  ==================================================================    *
  1327.  *                End                    *
  1328.  *  ==================================================================    */
  1329.